﻿using HamcoWcs.Models.Common;
using HamcoWcs.Models.DbInfos;
using HamcoWcs.Models.PlcInfos;
using Newtonsoft.Json;
using Snap7;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading;

namespace HamcoWcs.Models.Devices
{

    public sealed class PconPlc : SiemensPlc
    {
        public PconPlc(string plcName, PlcInfoDto plcInfo, List<DbInfoDto> dbInfo) : base(plcName, plcInfo, dbInfo)
        {
        }

        public void ClearRequest(PconDto con, DbInfoDto dbInfo)
        {
            con.Request = 0;
            int requestStart = con.RecvStartPoint + GlobalValue.CV_RECV_MSG_SIZE - 2;
            this.Client.DBWrite(dbInfo.DbNum, requestStart, 2, new byte[] { 0, 0 });
        }

        public Dictionary<int, PconDto> Pcons { get; set; } = new Dictionary<int, PconDto>();
        public List<RasterDto> Rasters { get; set; }
        protected override void OnAfterDisconnect()
        {
            foreach (var pcon in Pcons.Values)
            {
                pcon.PconMode = 0;
            }
        }

        public bool ReadDbBlock()
        {
            if (!this.ConnectionStatus) this.ConnectToPlc();
            if (!this.ConnectionStatus) return false;

            try
            {
                foreach (var db in DbInfo)
                {
                    //if (db.DbName.Contains("send")) continue;
                    byte[] recv = new byte[db.DbLength];
                    int res = this.Client.DBRead(db.DbNum, 0, db.DbLength, recv);
                    db.Buffer = recv;
                    // 读取error时断开连接
                    if (res != 0) throw new PlcCommunicationException($"DealRecv:read error,code: {res},times{ReadErrorTimes}");

                    Thread.Sleep(10);
                }
                ReadErrorTimes = 0;
            }
            catch (PlcCommunicationException ex)
            {
                ReadErrorTimes++;
                if (ReadErrorTimes >= 3)
                {
                    throw new Exception($"{PlcName}读取DB块失败");
                }
                else
                {
                    throw ex;
                }
            }
            catch (Exception)
            {
                ReadErrorTimes++;
                if (ReadErrorTimes >= 3)
                {
                    throw new Exception($"{PlcName}读取DB块失败");
                }
                else
                {
                    throw new PlcCommunicationException($"{PlcName}读取DB块失败,times{ReadErrorTimes}");
                }
            }


            return true;
        }

        public bool ReadDbBlock(string dbName)
        {
            return false;
        }
    }

    public class PconPlc1
    {
        public S7Client S7Client { get; set; } = new S7Client();
        public bool ConnectionStatus { get; set; }
        public string PlcName { get; }
        public PlcInfoDto PconPlcInfo { get; set; } = new PlcInfoDto();
        public List<DbInfoDto> PconDbInfo { get; set; } = new List<DbInfoDto>();
        public Dictionary<int, PconDto> Pcons { get; set; } = new Dictionary<int, PconDto>();

        public PconPlc1(string plcName)
        {
            PlcName = plcName;
        }

        public void ConnectToPlc()
        {
            int connectRe = this.S7Client.ConnectTo(this.PconPlcInfo.PlcIp, 0, 1);
            if (connectRe == 0)
            {
                this.ConnectionStatus = true;
                return;
            }
            this.ConnectionStatus = false;
        }

        public void DisconnectToPlc()
        {
            this.ConnectionStatus = false;
            this.S7Client.Disconnect();

            foreach (var con in this.Pcons.Values)
            {
                con.PconMode = 0;
            }
        }
    }
}